import {parseYvanPropChangeVJson} from '../../CtlUtils'
import webix from 'webix'
import _ from 'lodash'
import {CtlBase} from "../../CtlBase";
import {CtlInput} from "./CtlInput";
import {CtlEditorDefault} from "../../CtlDefaultValue";
import {YvEventDispatch} from "../../YvanEvent";

webix.protoUI(
    {
      name: 'editor',
      defaults: {},

      $init: function (config: any) {
        this.$view.innerHTML = `<textarea style="width:100%;height:100%;visibility:hidden;"></textarea>`
        this.$ready.push(this._ready)
        _.extend(this.config, config)
        if (config.on && typeof config.on.onInited === 'function') {
          config.on.onInited.call(this)
        }
      },
      _ready: function (this: any) {

      },
      _set_inner_size: function () {

      },
      _updateScrollSize: function () {

      },
      $setSize: function (x: any, y: any) {
        if (webix.ui.view.prototype.$setSize.call(this, x, y)) {
          this._set_inner_size()
        }
      }
    },
    webix.ui.view
)

export interface DataType {
  id: string,
  name: string,
  objectType?: DataType[]
  arrayType?: DataType[]
}

export class CtlEditor extends CtlInput<CtlEditor> {
  editor: any = null
  static create(module: any, vjson: any): CtlEditor {
    const that = new CtlEditor(vjson)
    that._module = module

    _.defaultsDeep(vjson, CtlEditorDefault)

    const yvanProp = parseYvanPropChangeVJson(vjson, ['value', 'width', 'height', 'uploadPath', 'savePath', 'filePostName', "linkedData", "paramDataType"])

    // 将 vjson 存至 _webixConfig
    that._webixConfig = vjson

    // 将 yvanProp 合并至当前 Ctl 对象, 期间会操作 _webixConfig
    _.assign(that, yvanProp)

    // 将 事件与 _webixConfig 一起存至 vjson 交给 webix 框架做渲染
    _.merge(vjson, that._webixConfig, {
      on: {
        onInited(this: any) {
          that.attachHandle(this, {...vjson, ...yvanProp})
          _.defer(() => {
            that.renderEditor()
          })
        },
        onAfterDelete() {
          that.removeHandle()
        }
      }
    })
    return that
  }

  renderEditor() {
    const editor = this._webix.$view.getElementsByTagName('textarea')[0]
    const me = this;
    // @ts-ignore
    KindEditor.ready(function (K) {
      me.editor = K.create(editor, {
        handle: me,
        items : [
          'source', '|', 'undo', 'redo', '|', 'preview', 'print', 'template', 'code', 'cut', 'copy', 'paste',
          'plainpaste', 'wordpaste', '|', 'justifyleft', 'justifycenter', 'justifyright',
          'justifyfull', 'insertorderedlist', 'insertunorderedlist', 'indent', 'outdent', 'subscript',
          'superscript', 'clearhtml', 'quickformat', 'selectall', '|', 'fullscreen', '/',
          'formatblock', 'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold',
          'italic', 'underline', 'strikethrough', 'lineheight', 'removeformat', '|', 'image', //'multiimage',
          'flash', 'media', 'insertfile', 'table', 'hr', 'emoticons', 'baidumap', 'pagebreak',
          'anchor', 'link', 'unlink', '|', 'custominsert', 'replaceparam'
        ],
        paramDataType: me.paramDataType,
        width: editor.parentElement.style.width,
        height: editor.parentElement.style.height,
        uploadJson: me.uploadPath,
        filePostName: me.filePostName,
        fileManagerJson: me.savePath,
        allowFileManager: true,
        afterCreate: function () {
          if (me.vjson.afterCreate) {
            YvEventDispatch(me.vjson.afterCreate, editor, null);
          }
        }
      });
      me.editor.html(me._value);
    });
  }

  // 替换文本域
  replaceparam() {
    if (this.isOriginal === true) {
      this._originalEditorHtml = this.editor.html();
      const container = this.editor.container[0].getElementsByTagName("iframe")[0].contentWindow.document.body
      this.listParamInfoList = [];
      this.objectParamInfoList = [];
      this.getParam(container.innerText);
      for (let i = 0; i < this.listParamInfoList.length; i++) {
        const el = this.listParamInfoList[i];
        const elements = $(container).find(":contains("+el.listPath+"[index])");
        _.set(el, "node", elements);
        for (let j = 0; j < elements.length; j++) {

          const element = elements[j];
          if (_.toUpper(element.tagName) === "TBODY") {

            let find = false;
            for (let n = 0; n < el.tables.length; n++) {
              if (el.tables[n].table === element) {
                find=true;
                break;
              }
            }
            if (find === false) {
              el.tables.push({table: element})
            }
          }

          if (_.toUpper(element.tagName) === "TR") {
            let find = false;
            let t = null;
            for (let n = 0; n < el.tables.length; n++) {
              if (el.tables[n].table === element.parentElement && el.tables[n].paramRow === element) {
                find=true;
                break;
              }
              t = el.tables[n];
            }
            if (find === false) {
              if (t && element.parentElement == t.table) {
                t.paramRow = element;
              }
            }
          }

        }
      }
      for (let i = 0; i < this.objectParamInfoList.length; i++) {
        const el: {param: string} = this.objectParamInfoList[i];
        _.set(el, "node", $(container).find(":contains("+el.param+")"));
      }

      /** 替换object数据 */
      for (let i = 0; i < this.objectParamInfoList.length; i++) {
        const el = this.objectParamInfoList[i];
        const path = el.param.substring(3,el.param.length-2);
        if (el.node) {
          for(let j = el.node.length - 1; j >= 0; j--) {
            const node = el.node[j];
            if (node.innerText.indexOf(el.param) >= 0) {
              // @ts-ignore
              node.innerHTML = node.innerHTML.replaceAll(el.param, _.get(this._linkedData, path));
            }
          }
        }
      }

      /** 替换list数据 */
      for (let i = 0; i < this.listParamInfoList.length; i++) {
        const el = this.listParamInfoList[i];
        const listData: any[] = _.get(this._linkedData, el.listPath);

        for (let m = 0; m < el.tables.length; m++) {
          let nel = _.cloneDeep(el.tables[m].paramRow?.outerHTML);
          for (let n = 0; n < listData.length; n++) {

            if (nel) {
              let nelT = _.cloneDeep(nel);
              for (let x = 0; x < el.subPath.length; x++) {
                // @ts-ignore
                nelT = nelT.replaceAll("${{"+el.listPath+"[index]" + el.subPath[x]+"}}", _.get(this._linkedData, el.listPath+"["+n+"]" + el.subPath[x]))
              }
              const objE = document.createElement("tbody");
              objE.innerHTML = nelT||"";
              el.tables[m].table?.append(objE.children[0]);
            }
            if (el.tables[m].table && el.tables[m].paramRow) {
              // @ts-ignore
              el.tables[m].table.removeChild(el.tables[m].paramRow);
              delete el.tables[m].paramRow
            }

          }
        }
      }

      this.isOriginal = false;
      // this.editor.readonly(true);
    } else {
      this.isOriginal = true;
      this.editor.html(this._originalEditorHtml);
      // this.editor.readonly(false);
    }
  }

  // 获取文本域
  getParam(content: string, startIndex: number = 0, isOpened: boolean = false) {
     const index = content.indexOf(isOpened?"}}":"${{", startIndex);
     if (index < 0) {
       return
     } else {
       if (isOpened) {
         let param = content.substring(startIndex, index + 2);
         let listTagIndex = param.indexOf("[index]")
         if (listTagIndex > 0) {
           const listPath = param.substring(3, listTagIndex);
           const subPath = param.substring(listTagIndex+7, param.length-2);
           let has = false;
           for (let i = 0; i<this.listParamInfoList.length; i++) {
             const lel = this.listParamInfoList[i];
             if (lel.listPath === listPath) {
               has = true;

               let subHas = false;
               for (let j = 0; j<lel.subPath.length; j++) {
                 const elp = lel.subPath[j];
                 if (elp === subPath) {
                   subHas = true;
                   break;
                 }
               }
               if (subHas === false) {
                 lel.subPath.push(subPath);
               }
               break;
             }
           }

           if (has === false) {
             this.listParamInfoList.push({listPath: listPath, subPath:[subPath], tables:[], node: null})
           }

         } else {
           let has = false;
           for (let i = 0; i<this.objectParamInfoList.length; i++) {
             if (this.objectParamInfoList[i].param === param) {
               has = true;break;
             }
           }
           if (has === false) {
             this.objectParamInfoList.push({param: param, node: null})
           }
         }
       }
       this.getParam(content, index, !isOpened);
     }
  }

  /*============================ 公共属性部分 ============================*/

  get isOriginal(): boolean {
    return this._isOriginal;
  }

  set isOriginal(value: boolean) {
    this._isOriginal = value;
    if (this._isOriginal) {
      $(".ke-toolbar-icon.ke-toolbar-icon-url.ke-icon-replaceparam").css("background-position", "0px -944px")
    } else {
      $(".ke-toolbar-icon.ke-toolbar-icon-url.ke-icon-replaceparam").css("background-position", "0px -688px")
    }
  }

  set value(nv: string) {
    this._value = nv;
    if (this.editor) {
      this.editor.html(nv);
    }
  }

  get value(): string {
    if (this.editor) {
      return this.editor.html();
    }
    return this._value;
  }

  getOriginalValue(): string {
    if (this.editor && this._isOriginal) {
      return this.editor.html();
    }
    return this._originalEditorHtml;
  }

  get uploadPath(): string {
    return this._uploadPath;
  }

  set uploadPath(nv: string) {
    this._uploadPath = nv;
  }

  get savePath(): string {
    return this._savePath;
  }

  set savePath(nv: string) {
    this._savePath = nv;
  }

  get width(): any {
    return this._width;
  }

  set width(nv: any) {
    this._width = nv;
    if (!this._webix) {
      if (nv) {
        this._webixConfig.width = nv
      } else {
        delete this._webixConfig.width
      }
      return
    }

    this._webix.define('width', nv)
    this._webix.resize()
  }

  get height(): any {
    return this._height;
  }

  set height(nv: any) {
    this._height = nv;
    if (!this._webix) {
      if (nv) {
        this._webixConfig.height = nv
      } else {
        delete this._webixConfig.height
      }
      return
    }

    this._webix.define('height', nv)
    this._webix.resize()
  }

  get linkedData(): any {
    return this._linkedData;
  }

  set linkedData(value: any) {
    this._linkedData = value;
  }

  get paramDataType(): DataType[] {
    return this._paramDataType;
  }

  set paramDataType(value: DataType[]) {
    if (_.isArray(value)) {
      this._paramDataType = value;
    }
  }

  /*============================ 私有属性部分 ============================*/

  private _value: string = ''

  /** 上传文件的路径 */
  private _uploadPath: string = ''

  /** 保存富文本的路径 */
  private _savePath: string = ''

  private _width: string = ''

  private _height: string = ''

  /** 上传文件的字段名称 */
  private filePostName: string = ''

  /** 文本域替换的数据源 */
  private _linkedData: any = {}

  /** 记录文本域替换前的文本值 */
  private _originalEditorHtml: string = ''

  /** 标记是否已经文本域替换 */
  private _isOriginal: boolean = true

  /** 记录文本域list表达式 */
  private listParamInfoList: {
    /** list的路径 */
    listPath: string,
    /** list元素的属性 */
    subPath: string[],
    tables: {
      /** 要替换内容的表格 */
      table: HTMLElement,
      /** 将会被复制替换的行 */
      paramRow?: HTMLElement
    }[],
    node: JQuery<HTMLElement> | null
  }[] = [];

  /** 记录文本域object表达式 */
  private objectParamInfoList: { node: JQuery<HTMLElement> | null, param: string }[] = [];

  /** 文本域参数类型 */
  private _paramDataType: DataType[] = [];
}
